/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.api.action.determination;

import com.inspur.edp.bef.api.be.IBEContext;
import com.inspur.edp.bef.api.be.IBENodeEntity;
import com.inspur.edp.bef.api.be.IBENodeEntityContext;
import com.inspur.edp.bef.api.lcp.IStandardLcp;
import com.inspur.edp.cef.api.determination.ICefDeterminationContext;
import com.inspur.edp.cef.api.message.IBizMessage;
import com.inspur.edp.cef.api.message.MessageLevel;
import com.inspur.edp.cef.spi.entity.resourceInfo.ModelResInfo;
import com.inspur.edp.cef.entity.changeset.IChangeDetail;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.variable.api.data.IVariableData;
import java.util.List;

/**
 * 联动规则上下文接口，用于在联动计算构件代码中获取当前数据行等信息
 * <p>除查询前联动计算等，联动计算可以挂到主表也可以挂到从（从）表。通常按照从主到子的顺序逐行触发。
 * {@link #getCurrentData()}、{@link #getTransactionData()}、{@link #getOriginalData()}方法提供了获取当前正在进行联动计算的数据行。
 * <p>此接口上的{@link #getBENodeEntity()}、{@link #getBEContext()}、{@link #getCurrentData()}
 * 等方法的返回值，均与联动计算所挂位置有关系。例如{@link #getCurrentData()}方法，当联动挂在主表上时，此方法返回主表实体数据；
 * 当联动挂在子表上时，此方法返回子表实体数据。
 * <p>常见问题说明：
 * <ul>
 *   <li>如何获取当前BE的configId或元数据Id：{@link #getModelResInfo()}.getConfigId()，{@link #getModelResInfo()}.getMetaDataId()；
 *   <li>如何当前联动计算挂在子表上，如何获取主表实体数据：{@link #getBEContext()}.getParentContext().getCurrentData()。
 *  </ul>
 */
public interface IDeterminationContext extends ICefDeterminationContext {

  /** 获取当前业务实体*/
  IBENodeEntity getBENodeEntity();

  /** 获取当前业务实体上下文*/
  IBENodeEntityContext getBEContext();

  @Deprecated
  IChangeDetail getRootChange();

  /**
   * 获取当前实体数据
   * <p>此方法相比{@link #getTransactionData()}，此方法返回值包含当前正在执行的动作中所产生的修改，
   * 而{@link #getTransactionData()}不包含。例如，假设当前动作是修改，修改内容为将X字段的值由A修改为B，且修改触发了当前联动计算，
   * 此时{@code getCurrentData()}方法返回值上的X字段值为B，{@code getTransactionData()}方法返回值上的X字段值为A。
   * <p>如果数据被删除，那么此方法返回{@code null}，如需获取删除前的数据：
   * <ul>
   *   <li>如果当前联动计算挂在修改后时机，通常应使用{@link #getTransactionData()}获取；
   *   <li>如果当前联动计算挂在保存前，通常应使用{@link #getOriginalData()}获取。
   * </ul>
   *
   * @return 实体数据
   *
   * @see #getTransactionData()
   * @see #getOriginalData()
   * @see IBEContext#getCurrentData()
   */
  IEntityData getCurrentData();

  /**
   * 获取从数据库加载的原始实体数据
   * <p>此方法返回值不包含任何未持久化的修改，换句话说，就是与数据库中的数据保持一致。
   * <p>如果数据是新增的，那么在执行保存之前，此方法返回值总为{@code null}。
   * <p>相反的，如果数据被删除，那么在执行保存之前，此方法返回值总不为{@code null}。
   * <p>原始实体数据是只读的不允许修改，如果修改将会引发{@link com.inspur.edp.cef.entity.accessor.base.ReadonlyDataException}。
   * @return 实体数据
   *
   * @see #getCurrentData()
   * @see #getTransactionData()
   * @see IBEContext#getOriginalData()
   */
  IEntityData getOriginalData();

  /**
   * 获取事务级实体数据
   * 事务级实体数据，包含未进行持久化的已被接受的变更，但不包含正在执行的动作所产生的变更。
   * <p>假设当前联动被保存动作触发：
   * <ul>
   *   <li>如果保存之前数据已被删除，那么此方法返回值为{@code null}；
   *   <li>如果数据在保存前联动中被删除，那么此方法返回值不为{@code null}；
   *   <li>如果数据是在保存前联动中新增的，那么此方法返回值为{@code null}。
   * </ul>
   * <p>事务级实体数据是只读的不允许修改，如果修改将会引发{@link com.inspur.edp.cef.entity.accessor.base.ReadonlyDataException}。
   * @return 实体数据
   *
   * @see #getCurrentData()
   * @see #getOriginalData()
   * @see IBEContext#getTransactionData()
   */
  IEntityData getTransactionData();

  /** 获取该联动规则所在的实体编号，可能是主表实体的编号，也可能是子表实体的编号  */
  String getNodeCode();

  void setNodeCode(String value);

  /** @see #getCurrentData() */
  IEntityData getCurrentEntityData();

  /**
   * 向LCP中添加由消息
   * <p>其参数可通过{@link #createMessageWithLocation(MessageLevel, String, String...)}
   * 或{@link #createMessageWithLocation(MessageLevel, List, String, String...)}方法创建。
   *
   * @param msg 消息体
   */
  void addMessage(IBizMessage msg);

  /**
   * 创建消息
   *
   * @param level 消息级别：类型包括成功执行Success、提示消息Info、警告Warning、错误Error
   * @param msg 消息文本内容
   * @param msgPars 消息参数
   * @return 消息
   */
  IBizMessage createMessageWithLocation(MessageLevel level, String msg, String... msgPars);

  /**
   * 为该联动规则创建消息
   *
   * @param level 消息级别：类型包括成功执行Success、提示消息Info、警告Warning、错误Error
   * @param columnNames 消息位置列名
   * @param msg 消息文本内容
   * @param msgPars 消息参数
   * @return 消息
   */
  IBizMessage createMessageWithLocation(
      MessageLevel level, java.util.List<String> columnNames, String msg, String... msgPars);

  /**
   * 根据指定configId创建Lcp
   * <p>这是一个在联动计算中调用其他be接口时的便捷接口。
   * 其作用与{@link com.inspur.edp.bef.api.lcp.ILcpFactory#createLcp(String)}完全一致。
   *
   * @param configId
   * @return Lcp
   *
   * @see com.inspur.edp.bef.api.lcp.ILcpFactory#createLcp(String)
   */
   IStandardLcp getLcp(String configId);

  IVariableData getVariables();

  /**获取当前业务实体的ConfigId，如果当前业务实体为运行时定制扩展业务实体，那么此方法返回扩展业务实体的ConfigId（扩展业务实体的ConfigId与基础业务实体的ConfigId通常相似但不相同）*/
  String getConfigId();

  //region i18n
  /**
   * 获取当前模型信息
   * <p>也包含国际化资源信息
   *
   * @return 模型信息
   */
  ModelResInfo getModelResInfo();

  /**
   * 获取当前语言下的唯一性约束提示信息
   *
   * @param conCode
   * @return 提示信息
   */
  String getUniqueConstraintMessage(String conCode);

  //endregion
}
